package cooperated

import (
	"bytes"
	"fmt"
	"math"
	"runtime/debug"
	"strings"
	"sync"

	"gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/common/feature/orbit/chess_protocol"
	"gddgame.cc/galaxy/common/namespaces/cooperate"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/common/service/pathfinding"
	"gddgame.cc/galaxy/project/breeder/breeder/center"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/serialize"
)

//go:generate msgp

const (
	Id       = cooperate.Id
	Position = cooperate.Position
	MapNoId  = cooperate.MapNoId
	Ignore   = cooperate.Ignore // 是否忽略：1忽略，0不忽略， 用于建造或者返回到基地

	// Attr中Data设置，可进行增加减少，直接根据key存储
	Health    = cooperate.Health // 耐久度，为0会触发销毁计划
	AllHealth = "allHealth"      // 总耐久
	Healths   = "healths"        // 分血条

	// Attr中设置，非战斗属性，可根据buff实现动态变更
	// 变更时间存储在cool逻辑中
	Speed       = "speed"       // 移动速度
	SpeedChange = "speedChange" // 移动速度加成
	View        = "view"        // 视野

	Identity  = cooperate.Identity
	Open      = "open"
	Type      = "type"
	Positions = "positions" // 路径或占位
	Plan      = "plan"      // 路径规划
	PlanIndex = "planIndex" // 当前行径节点
	Direction = "direction" // 方向

	Distance        = "distance"       // 距离：设置后
	Visible         = "visible"        // 可见
	MoveStatus      = "moveStatus"     // 移动状态
	Combat          = "combat"         // 战斗状态
	AttackTarget    = "attackTarget"   // 当前攻击目标
	AttackBehavior  = "attackBehavior" // 当前已使用技能
	LastRegion      = "lastRegion"     // 最后归属region，死亡后恢复坐标
	LastStop        = "lastStop"       // 最后停留点，驻守攻击后返回该点
	DirectIds       = "directIds"      // 指令列表
	DirectCool      = "directCool"     // 指令冷却列表
	Key             = cooperate.Key
	Name            = "name"                      // 显示名称
	TargetMode      = "targetMode"                // 攻击目标模式
	BuildMode       = "buildMode"                 // 建筑模式
	Obvious         = "obvious"                   // 可见对象： 0、全都可见，1、自己可见，2、同盟可见，3、势力可见
	AttrAbility     = "attrAbility"               // 属性
	BuffAbility     = "buffAbility"               // buff
	AiMode          = model.DefineAiMode          // 部队停留ai模式：0，停留，1，防御，2，驻守
	BehaviorPattern = model.DefineBehaviorPattern // 行为模式：Ai行为树定义，0为手动，其他都是在Ai行为树管理中

	Level = "level" // 等级

	Behaviors = "behaviors" // 攻击行为内容

	// time
	LastAttackTime = "lastAttackTime" // 最后一次攻击到期时间：用来进行触发技能逻辑，

	HoldBaseTime = "holdBaseTime" // 占领到达时间：可以判断是否在占领阶段，中断占领

	CrossedTime      = "crossedTime"      // 援护状态，不能移动
	CrossedStartTime = "crossedStartTime" // 进入援护时间：用来矫正援护有效
	BeCrossItem      = "beCrossItem"      // 被援护人，用来清除无效援护
	CrossedItem      = "crossedItem"      // 援护人，系统内部用
	BeCrossTime      = "beCrossTime"      // 被援护状态，不能停留
	BeCrossStartTime = "beCrossStartTime" // 进入被援护状态，用来矫正有效时间

	RecoveryTime = "recoveryTime"
	BuildTime    = "buildTime"
	DestroyTime  = "destroyTime"

	// 持续行为
	DoSustain  = "doSustain"  // 在做的事
	UnitStatus = "unitStatus" // 部队总状态

	ReadyBehaviorSustain = "readyBehavior" // 技能准备时间：可以判断是否在技能准备阶段，打断技能

	// 本地数据
	InjuryData = "injuryData"

	Listen = "listen" // 注入寻路系统

	// Node data
	HoldStatus = "holdStatus" // 占领状态： 0 未占领，1 占领，2 毁坏

	// prop prefix, 用来扩展冷却时间
	DirectCoolPrefix  = "dc"
	DirectValidPrefix = "dv"

	// 依赖字段设定
	AiUnit     = "aiUnit"     // ai unit绑定在region，force等manager上
	AiBuild    = "aiBuild"    // ai build绑定在region，force等manager上
	AiFortress = "aiFortress" // 设定在
	AiForce    = "aiForce"    // 建立在unit和build上的
)

const (
	NoneHoldStatus    byte = 0
	HoldedStatus      byte = 1
	DestroyHoldStatus byte = 2
)

const (
	AccountDataType  = cooperate.AccountDataType
	NodeDataType     = cooperate.NodeDataType
	PathNodeDataType = cooperate.PathNodeDataType
	ForceDataType    = cooperate.ForceDataType
	UnitDataType     = "unit"
	BuildDataType    = "build"
	ItemDataType     = "item"
	AllianceDataType = "alliance" // alliance管理fortress
	FortressDataType = "fortress" // 要塞管理范围内的build，以及对应逻辑创建的ai部队
	RegionDataType   = "region"   // 区域
)

const (
	IdentityManage = "identityManage"
	KeyManage      = "keyManage"
	IK             = "ik"
	IKManage       = "ikManage"
)
const (
	AccountType  structure.PublicDataType = center.AccountType
	NodeType     structure.PublicDataType = center.NodeType
	PathNodeType structure.PublicDataType = center.PathNodeType
	ForceType    structure.PublicDataType = center.ForceType
	BuildType    structure.PublicDataType = center.BuildType
	UnitType     structure.PublicDataType = center.UnitType
	ItemType     structure.PublicDataType = center.ItemType
	AllianceType structure.PublicDataType = center.AllianceType
	FortressType structure.PublicDataType = center.FortressType
	RegionType   structure.PublicDataType = center.RegionType
)

const (
	BuffAbilityExtend structure.ExtendType = "buffAbility"
	ShowExtend        structure.ExtendType = "show"
	DirectCoolExtend  structure.ExtendType = "directCool"
	DefineExtend      structure.ExtendType = "define"
)

var (
	ExtendModeMap = map[structure.ExtendType]structure.ExtendMode{
		BuffAbilityExtend: structure.SortedExtendMode,
		ShowExtend:        structure.ListExtendMode,
	}
)

const (
	ListenRelation byte = 0
)
const (
	NormalMoveMode byte = iota
	AutoAttackMoveMode
	AttackTargetMode
)

const (
	Normal cooperate.MoveStatus = iota
	Auto
	FinishAuto
)

const (
	AttackTaskEvent structure.TaskEvent = iota
	DestroyAttackTaskEvent
	CreateTaskEvent
	UpdateTaskEvent
	DestroyTaskEvent
	DirectTaskEvent
)

const (
	_                   byte = iota
	AttackSystemEvent        // 攻击->触发任务
	EnterSystemEvent         // 进入节点：
	LeaveSystemEvent         // 离开节点：
	BeAttackSystemEvent      // 被攻击->触发攻击计划
	BeSearchSystemEvent      // 被探查->触发攻击计划

	// 节点事件：每次进入节点，到达
	ListenSystemEvent

	// inline Event
	ArriveInlineEvent = 200 // 内部移动到达事件
)

var (
	PersistenceMap = map[string]bool{
		LastRegion: true,
		LastStop:   true,
		AiMode:     true,
		TargetMode: true,

		cooperate.ManageDataType: true,
		ForceDataType:            true,
		FortressDataType:         true,
		RegionDataType:           true,
		AllianceDataType:         true,
		UnitDataType:             true,
		BuildDataType:            true,
		ItemDataType:             true,
		IdentityManage:           true,
		KeyManage:                true,
		IKManage:                 true,
	}
	DefineSyncMap = map[structure.PublicDataType]map[string][]string{}
	AccountField  = cooperate.NewFieldsDefine(AccountType, AccountDataType).
			SetNo(true).
			BindBeDepend(UnitDataType, UnitType, AccountDataType, false).
			BindBeDepend(BuildDataType, BuildType, AccountDataType, false).
			BindBeDepend(ItemDataType, ItemType, AccountDataType, false).
			Bind(OpenPropType, FromOpenProp).
			Bind(MapPropType, FromMapProp).
			Bind(AbilityPropType, FromAbilityProp).
			Bind(SyncPropType, FromSyncProp).
			Bind(cooperate.InstancePropType, FromAccountProp)
	BuildField = cooperate.NewFieldsDefine(BuildType, BuildDataType).
			SetPosition(true).
			SetChess(true).
			BindBeDepend(UnitDataType, UnitType, BuildDataType, true).
			Bind(NodePropType, FromNodeProp).
			Bind(MapPropType, FromMapProp).
			Bind(FixPropType, FromFixProp).
			Bind(AbilityPropType, FromAbilityProp).
			Bind(BattlePropType, FromBattleProp).
			Bind(SyncPropType, FromSyncProp).
			Bind(cooperate.InstancePropType, FromBuildProp)
	UnitField = cooperate.NewFieldsDefine(UnitType, UnitDataType).
			SetChess(true).
			SetId(true).
			Bind(IdPropType, FromIdProp).
			Bind(MapPropType, FromMapProp).
			Bind(MovePropType, FromMoveProp).
			Bind(AbilityPropType, FromAbilityProp).
			Bind(BattlePropType, FromBattleProp).
			Bind(SyncPropType, FromSyncProp).
			Bind(cooperate.InstancePropType, FromUnitProp)
	NodeField = cooperate.NewFieldsDefine(NodeType, NodeDataType).
			SetChess(true).
			SetPosition(true).
			Bind(NodePropType, FromNodeProp).
			Bind(MapPropType, FromMapProp).
			Bind(SyncPropType, FromSyncProp)
	PathNodeField = cooperate.NewFieldsDefine(PathNodeType, PathNodeDataType).
			SetChess(false).
			SetPosition(true).
			Bind(NodePropType, FromNodeProp).
			Bind(MapPropType, FromMapProp)
	ItemField = cooperate.NewFieldsDefine(ItemType, ItemDataType).
			SetNo(true).
			SetChess(true).
			SetMap(true).
			Bind(NoPropType, FromNoProp).
			Bind(MapPropType, FromMapProp).
			Bind(FixPropType, FromFixProp).
			Bind(AbilityPropType, FromAbilityProp).
			Bind(BattlePropType, FromBattleProp).
			Bind(SyncPropType, FromSyncProp)
	FortressField = cooperate.NewFieldsDefine(FortressType, FortressDataType).
			SetPosition(true).
			SetMap(true).
			SetManage(true).
			BindBeDepend(UnitDataType, UnitType, FortressDataType, false).
			BindBeDepend(AiUnit, UnitType, AiFortress, false).
			BindBeDepend(BuildDataType, BuildType, FortressDataType, false).
			BindBeDepend(AiBuild, BuildType, AiFortress, false).
			Bind(MapPropType, FromMapProp)
	RegionField = cooperate.NewFieldsDefine(RegionType, RegionDataType).
			SetPosition(true).
			SetMap(true).
			SetManage(true).
			BindBeDepend(NodeDataType, NodeType, RegionDataType, false).
			Bind(MapPropType, FromMapProp)
	ForceField = cooperate.NewFieldsDefine(ForceType, ForceDataType).
			SetMap(true).
			SetManage(true).
			SetNo(true).
			BindBeDepend(AiUnit, UnitType, AiForce, false).
			BindBeDepend(AiBuild, BuildType, AiForce, false).
			BindBeDepend(NodeDataType, NodeType, ForceDataType, false)
	AllianceField = cooperate.NewFieldsDefine(AllianceType, AllianceDataType).
			SetManage(true).
			SetNo(true).
			BindBeDepend(AccountDataType, AccountType, AllianceDataType, false)
	ManageField = cooperate.NewFieldsDefine(cooperate.ManageType, cooperate.ManageDataType).
			SetPosition(false).
			SetMap(true).
			BindBeDepend(UnitDataType, UnitType, cooperate.ManageDataType, false).
			BindBeDepend(ItemDataType, ItemType, cooperate.ManageDataType, false).
			BindBeDepend(Identity+UnitDataType, UnitType, IdentityManage, false).
			BindBeDepend(Identity+ItemDataType, ItemType, IdentityManage, false).
			BindBeDepend(Key+UnitDataType, UnitType, KeyManage, false).
			BindBeDepend(Key+ItemDataType, ItemType, KeyManage, false).
			BindBeDepend(IK+UnitDataType, UnitType, IKManage, false).
			BindBeDepend(IK+ItemDataType, ItemType, IKManage, false).
			BindBeDepend(BuildDataType, BuildType, cooperate.ManageDataType, false).
			BindBeDepend(NodeDataType, NodeType, cooperate.ManageDataType, false).
			BindBeDepend(FortressDataType, FortressType, cooperate.ManageDataType, false).
			BindBeDepend(RegionDataType, RegionType, cooperate.ManageDataType, false).
			BindBeDepend(Identity+BuildDataType, BuildType, IdentityManage, false).
			BindBeDepend(Identity+NodeDataType, NodeType, IdentityManage, false).
			BindBeDepend(Identity+FortressDataType, FortressType, IdentityManage, false).
			BindBeDepend(Identity+RegionDataType, RegionType, IdentityManage, false).
			BindBeDepend(Key+BuildDataType, BuildType, KeyManage, false).
			BindBeDepend(Key+NodeDataType, NodeType, KeyManage, false).
			BindBeDepend(IK+BuildDataType, BuildType, IKManage, false).
			BindBeDepend(IK+NodeDataType, NodeType, IKManage, false)
	DataTypeFieldMap = map[structure.PublicDataType]*cooperate.FieldsDefine{
		AccountType:          AccountField,
		BuildType:            BuildField,
		UnitType:             UnitField,
		NodeType:             NodeField,
		PathNodeType:         PathNodeField,
		ItemType:             ItemField,
		FortressType:         FortressField,
		RegionType:           RegionField,
		ForceType:            ForceField,
		AllianceType:         AllianceField,
		cooperate.ManageType: ManageField,
	}
	HoldBattleTime = 30 * 1000 // 30s,系统以毫秒做计划任务
)

const (
	_ cooperate.LogicType = iota // 设定
	AttackLogicType
	ListenLogicType
	SearchLogicType        // 探查
	MapManualLogicType     // 地图释放
	TauntLogicType         // 嘲讽
	RepairLogicType        // 维修
	SpeedTeleportLogicType // 瞬移
	SnipeLogicType         // 狙击

	HoldLogicType = 127 // 占领逻辑

	CustomLogicType = 250 // 自定义逻辑
)

const (
	_                     cooperate.LogicType = iota // 设定
	BatchUpdateCustomType                            //批量更新
	BatchOperateCustomType
)

type AiModeDefine byte

const (
	StopAiMode    AiModeDefine = iota // 停留
	DefenseAiMode                     // 防御
	DefendAiMode                      // 驻守
)

type TargetModeDefine byte

const (
	NoneTargetMode     TargetModeDefine = 0
	DistanceTargetMode                  = 1 << 0
	HealthTargetMode                    = 1 << 1

	DescTargetMode = 1 << 2
)

type TargetIdentity int

const (
	NeutralTargetIdentity   TargetIdentity = 1 << 0
	SelfTargetIdentity      TargetIdentity = 1 << 1
	PartnerTargetIdentity   TargetIdentity = 1 << 2
	EnemyTargetIdentity     TargetIdentity = 1 << 3
	CanAttackTargetIdentity                = NeutralTargetIdentity | EnemyTargetIdentity
)

type TargetRange byte

const (
	DistanceTargetRange TargetRange = 0
	PositionTargetRange             = 1
)

const (
	FirstIdentityType  = 1 << 30
	SecondIdentityType = 1 << 29
	ThirdIdentityType  = 1 << 28
	BaseIdentityType   = FirstIdentityType | SecondIdentityType | ThirdIdentityType
)

var (
	IdentityList = []int{FirstIdentityType, SecondIdentityType, ThirdIdentityType}
)

type TargetVisible int

const (
	NormalTargetVisible TargetVisible = 0
	FirstTargetVisible  TargetVisible = FirstIdentityType
	SecondTargetVisible TargetVisible = SecondIdentityType
	ThirdTargetVisible  TargetVisible = ThirdIdentityType
)

//msgp:tuple AccountDefine
type AccountDefine struct {
	Type byte          `json:"type" msg:"type"`
	Attr []interface{} `json:"attr" msg:"attr"`
}

type ExtendMapByte [][]byte

type EventMap struct {
	HoldBase    *structure.EventData `json:"holdBase" msg:"holdBase"`
	BreakBase   *structure.EventData `json:"breakBase" msg:"breakBase"`
	DestroyBase *structure.EventData `json:"destroyBase" msg:"destroyBase"`

	OnHoldBase    *structure.EventData `json:"onHoldNode" msg:"onHoldNode"`
	OnDestroyBase *structure.EventData `json:"onDestroyNode" msg:"onDestroyNode"`

	ReadyBehavior *structure.EventData `json:"readyBehavior" msg:"readyBehavior"`
	BreakBehavior *structure.EventData `json:"breakBehavior" msg:"breakBehavior"`

	Move   *structure.EventData `json:"move" msg:"move"`
	Wait   *structure.EventData `json:"wait" msg:"wait"`
	Arrive *structure.EventData `json:"arrive" msg:"arrive"`

	Teleport      *structure.EventData `json:"teleport" msg:"teleport"`
	SpeedTeleport *structure.EventData `json:"speedTeleport" msg:"speedTeleport"`

	OnTeleportIn  *structure.EventData `json:"onTeleportIn" msg:"onTeleportIn"`
	OnTeleportOut *structure.EventData `json:"onTeleportOut" msg:"onTeleportOut"`

	PutUnit  *structure.EventData `json:"putUnit" msg:"putUnit"`
	DownUnit *structure.EventData `json:"downUnit" msg:"downUnit"`
}

func NewEventMap(logic cooperate.LogicOperate, messageMap map[string]*model.SettingMessage) *EventMap {
	event := &EventMap{}

	event.HoldBase = event.Event(logic, messageMap["HoldBase"])
	event.BreakBase = event.Event(logic, messageMap["BreakBase"])
	event.DestroyBase = event.Event(logic, messageMap["DestroyBase"])
	event.OnHoldBase = event.Event(logic, messageMap["OnHoldBase"])
	event.OnDestroyBase = event.Event(logic, messageMap["OnDestroyBase"])
	event.ReadyBehavior = event.Event(logic, messageMap["ReadyBehavior"])
	event.BreakBehavior = event.Event(logic, messageMap["BreakBehavior"])
	event.Move = event.Event(logic, messageMap["Move"])
	event.Wait = event.Event(logic, messageMap["Wait"])
	event.Arrive = event.Event(logic, messageMap["Arrive"])
	event.Teleport = event.Event(logic, messageMap["Teleport"])
	event.SpeedTeleport = event.Event(logic, messageMap["SpeedTeleport"])
	event.OnTeleportIn = event.Event(logic, messageMap["OnTeleportIn"])
	event.OnTeleportOut = event.Event(logic, messageMap["OnTeleportOut"])
	event.PutUnit = event.Event(logic, messageMap["PutUnit"])
	event.DownUnit = event.Event(logic, messageMap["DownUnit"])

	return event
}

func (eventMap *EventMap) Event(logic cooperate.LogicOperate, message *model.SettingMessage) *structure.EventData {
	if message == nil {
		debug.PrintStack()
		fmt.Println("event miss")
		return nil
	}
	data := logic.EventBuilder().Operate(logic.OperateBuilder().SendMessage(nil, byte(message.No), nil, message.Params), nil).Data()
	return &data
}

type ExtendMap struct {
	Regions   *cooperate.PositionSlice       `json:"regions" msg:"regions"`
	Builds    *cooperate.DataDefineNodeSlice `json:"builds" msg:"builds"`
	Resources *cooperate.DataDefineNodeSlice `json:"resources" msg:"resources"`

	list    map[int]serialize.UnSerializer
	intList []int
}

func NewExtendMap() *ExtendMap {
	em := &ExtendMap{
		Regions:   &cooperate.PositionSlice{},
		Builds:    &cooperate.DataDefineNodeSlice{},
		Resources: &cooperate.DataDefineNodeSlice{},

		list: map[int]serialize.UnSerializer{},
	}

	em.list[len(em.list)] = em.Regions
	em.list[len(em.list)] = em.Builds
	em.list[len(em.list)] = em.Resources
	em.list[len(em.list)] = &ExtendMapItem{
		ExtendMap: em,
		Name:      "DestroyTime",
	}
	em.list[len(em.list)] = &ExtendMapItem{
		ExtendMap: em,
		Name:      "HoldTime",
	}

	return em
}

type ExtendMapItem struct {
	ExtendMap *ExtendMap
	Name      string
}

//msgp IntExtend
type IntExtend int

//msgp ByteSliceExtend
type ByteSliceExtend [][]byte

func (emi *ExtendMapItem) UnSerialize(data []byte) error {
	return nil
}

func (eMap *ExtendMap) Parse(data []byte) error {
	b := ExtendMapByte{}
	_, err := b.UnmarshalMsg(data)
	if err != nil {
		return err
	}
	for index, bb := range b {
		if len(eMap.list) <= index {
			return nil
		}
		err := eMap.list[index].UnSerialize(bb)
		if err != nil {
			fmt.Println(3, index)
			return err
		}
	}
	return nil
}

const OpenPropType cooperate.PropType = "openProp"

//msgp:tuple OpenProp
type OpenProp struct {
	Id   int    `json:"id" msg:"id"`
	Open string `json:"open" msg:"open"`

	t structure.PublicDataType `json:"-" msg:"-"`
}

func NewOpenProp(t structure.PublicDataType, id int, open string) *OpenProp {
	return &OpenProp{
		Id:   id,
		Open: open,
		t:    t,
	}
}
func ReceiveOpenProp(instance cooperate.PropsInstance) *OpenProp {
	prop := instance.Receive(OpenPropType)
	if prop == nil {
		return nil
	}
	return prop.(*OpenProp)
}
func FromOpenProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Id, Open).BindChess(Id, Open).BindPersistence(Id, Open)
}
func (prop *OpenProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Id, prop.Open)
}
func (prop *OpenProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Id:
		prop.Id = utils.ToInt(value)
		return prop.Id, true
	case Open:
		prop.Open = utils.ToString(value)
		return prop.Open, true
	}
	return nil, false
}
func (prop *OpenProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

const NoPropType cooperate.PropType = "noProp"

//msgp:tuple NoProp
type NoProp struct {
	Id       int    `json:"id" msg:"id"`
	Name     string `json:"name" msg:"name"`
	Account  int    `json:"account" msg:"account"`
	Alliance int    `json:"alliance" msg:"alliance"`

	t structure.PublicDataType `json:"-" msg:"-"`
}

// account = -1 则不同步
// id = nil 则是同步Data，id!=nil 则是同步SingleData
func NewNoProp(instance cooperate.PropsInstance) *NoProp {
	return &NoProp{
		Id:       utils.ToInt(instance.GetId()),
		Name:     instance.ToString(Name),
		Account:  instance.ToInt(AccountDataType),
		Alliance: instance.ToInt(AllianceDataType),

		t: instance.GetDataType(),
	}
}
func ReceiveNoProp(instance cooperate.PropsInstance) *NoProp {
	prop := instance.Receive(NoPropType)
	if prop == nil {
		return nil
	}
	return prop.(*NoProp)
}
func FromNoProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Id, Name, AccountDataType, AllianceDataType).BindChess(Id, Name, AccountDataType, AllianceDataType).BindPersistence(Id, Name, AccountDataType, AllianceDataType)
}
func (prop *NoProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Id, prop.Name, prop.Account, prop.Alliance)
}

func (prop *NoProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Id:
		prop.Id = utils.ToInt(value)
		return prop.Id, true
	case Name:
		prop.Name = utils.ToString(value)
		return prop.Name, true
	case AccountDataType:
		prop.Account = utils.ToInt(value)
		return prop.Account, true
	case AllianceDataType:
		prop.Alliance = utils.ToInt(value)
		return prop.Alliance, true
	}
	return nil, false
}
func (prop *NoProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

func (prop *NoProp) GetDataType() structure.PublicDataType {
	return prop.t
}
func (prop *NoProp) GetId() interface{} {
	return prop.Id
}
func (prop *NoProp) GetItem() []byte {
	return prop.Bytes()
}
func (prop *NoProp) Bytes() []byte {
	v := &structure.BaseData{
		DataType: prop.t,
		Id:       prop.Id,
	}
	return v.Bytes()
}

const IdPropType cooperate.PropType = "idProp"

//msgp:tuple IdProp
type IdProp struct {
	Id       string `json:"id" msg:"id"`
	Name     string `json:"name" msg:"name"`
	Account  int    `json:"account" msg:"account"`
	Alliance int    `json:"alliance" msg:"alliance"`

	t structure.PublicDataType `json:"-" msg:"-"`
}

// account = -1 则不同步
// id = nil 则是同步Data，id!=nil 则是同步SingleData
func NewIdProp(instance cooperate.PropsInstance) *IdProp {
	return &IdProp{
		Id:       instance.ToString(Id),
		Name:     instance.ToString(Name),
		Account:  instance.ToInt(AccountDataType),
		Alliance: instance.ToInt(AllianceDataType),
		t:        instance.GetDataType(),
	}
}
func ReceiveIdProp(instance cooperate.PropsInstance) *IdProp {
	prop := instance.Receive(NodePropType)
	if prop == nil {
		return nil
	}
	return prop.(*IdProp)
}
func FromIdProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Id, Name, AccountDataType, AllianceDataType).BindChess(Id, Name, AccountDataType, AllianceDataType).BindPersistence(Id, Name, AccountDataType, AllianceDataType)
}
func (prop *IdProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Id, prop.Name, prop.Account, prop.Alliance)
}

func (prop *IdProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Id:
		prop.Id = utils.ToString(value)
		return prop.Id, true
	case Name:
		prop.Name = utils.ToString(value)
		return prop.Name, true
	case AccountDataType:
		prop.Account = utils.ToInt(value)
		return prop.Account, true
	case AllianceDataType:
		prop.Alliance = utils.ToInt(value)
		return prop.Alliance, true
	}
	return nil, false
}
func (prop *IdProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

func (prop *IdProp) GetDataType() structure.PublicDataType {
	return prop.t
}
func (prop *IdProp) GetId() interface{} {
	return prop.Id
}
func (prop *IdProp) GetItem() []byte {
	return prop.Bytes()
}
func (prop *IdProp) Bytes() []byte {
	v := &structure.BaseData{
		DataType: prop.t,
		Id:       prop.Id,
	}
	return v.Bytes()
}

const NodePropType cooperate.PropType = "nodeProp"

//msgp:tuple NodeProp
type NodeProp struct {
	Id       []byte `json:"id" msg:"id"`
	Name     string `json:"name" msg:"name"`
	Account  int    `json:"account" msg:"account"`
	Alliance int    `json:"alliance" msg:"alliance"`

	t structure.PublicDataType `json:"-" msg:"-"`
}

// account = -1 则不同步
// id = nil 则是同步Data，id!=nil 则是同步SingleData
func NewNodeProp(instance cooperate.PropsInstance) *NodeProp {
	return &NodeProp{
		Id:       instance.ToBytes(Position),
		Name:     instance.ToString(Name),
		Account:  instance.ToInt(AccountDataType),
		Alliance: instance.ToInt(AllianceDataType),
		t:        instance.GetDataType(),
	}
}
func ReceiveNodeProp(instance cooperate.PropsInstance) *NodeProp {
	prop := instance.Receive(NodePropType)
	if prop == nil {
		return nil
	}
	return prop.(*NodeProp)
}
func FromNodeProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Id, Name, AccountDataType, AllianceDataType).BindChess(Id, Name, AccountDataType, AllianceDataType).BindPersistence(Id, Name, AccountDataType, AllianceDataType)
}
func (prop *NodeProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Id, prop.Name, prop.Account, prop.Alliance)
}

func (prop *NodeProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Id:
		prop.Id = utils.ToBytes(value)
		return prop.Id, true
	case Name:
		prop.Name = utils.ToString(value)
		return prop.Name, true
	case AccountDataType:
		prop.Account = utils.ToInt(value)
		return prop.Account, true
	case AllianceDataType:
		prop.Alliance = utils.ToInt(value)
		return prop.Alliance, true
	}
	return nil, false
}
func (prop *NodeProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

func (prop *NodeProp) GetDataType() structure.PublicDataType {
	return prop.t
}
func (prop *NodeProp) GetId() interface{} {
	return prop.Id
}
func (prop *NodeProp) GetItem() []byte {
	return prop.Bytes()
}
func (prop *NodeProp) Bytes() []byte {
	v := &structure.BaseData{
		DataType: prop.t,
		Id:       prop.Id,
	}
	return v.Bytes()
}

const SyncPropType cooperate.PropType = "syncProp"

//msgp:tuple SyncProp
type SyncProp struct {
	//Show   []chess_protocol.ExtendItem `json:"show" msg:"show"`
	Define []chess_protocol.ExtendItem `json:"special" msg:"special"`

	instance cooperate.PropsInstance `json:"-" msg:"-"`
}

func NewSyncProp(instance cooperate.PropsInstance, extendMap map[structure.ExtendType]interface{}) *SyncProp {
	//var e []interface{}
	//if extendMap[ShowExtend] != nil {
	//	e = utils.ToInterfaceSlice(extendMap[ShowExtend])
	//} else {
	//	e = []interface{}{}
	//}

	syncProp := &SyncProp{instance: instance}
	//syncProp.Show = make([]chess_protocol.ExtendItem, len(e))
	//for index, value := range e {
	//	syncProp.Show[index] = chess_protocol.ExtendItem{No: index, Value: value}
	//}

	define := instance.GetDefineList(instance.GetDataType(), instance.ToString(Key))
	syncProp.Define = make([]chess_protocol.ExtendItem, len(define))
	for index, value := range define {
		syncProp.Define[index] = chess_protocol.ExtendItem{No: index, Value: instance.ToInt(value)}
	}

	return syncProp
}
func ReceiveSyncProp(instance cooperate.PropsInstance) *SyncProp {
	prop := instance.Receive(SyncPropType)
	if prop == nil {
		return nil
	}
	return prop.(*SyncProp)
}
func FromSyncProp(fd *cooperate.FieldsDefine) {
	//fd.BindNoticeExtend(ShowExtend, func(execute *structure.Execute, conn structure.SafeConn, instance cooperate.PropsInstance, extend structure.ExtendType) interface{} {
	//	result := execute.GetListExtend(conn, instance, ShowExtend)
	//	return result
	//}, false).BindChessExtend(ShowExtend).BindPersistence(string(ShowExtend))
	fd.BindNoticeExtend(DefineExtend, nil, false).BindChessExtend(DefineExtend)
}
func (prop *SyncProp) ChessProp(data *chess_protocol.Data) {
	data.Extend = append(data.Extend, prop.Define)
}
func (prop *SyncProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}
func (prop *SyncProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	if extend == DefineExtend {
		define := prop.instance.GetDefineList(prop.instance.GetDataType(), prop.instance.ToString(Key))
		if total.Reset != nil {
			//fmt.Println("extend reset", total.Reset, prop.Define)
			prop.Define = total.Reset

			for index, value := range define {
				prop.instance.MergeProp(value, prop.Define[index])
			}
		} else {
			//fmt.Println("extend list", total.List, prop.Define)
			for _, value := range total.List {
				if len(prop.Define) <= int(value.Key) {
					prop.Define = append(prop.Define, make([]chess_protocol.ExtendItem, int(value.Key)-len(prop.Define)+1)...)
				}
				prop.Define[value.Index] = chess_protocol.ExtendItem{Value: value.Value, No: int(value.Key)}
				//fmt.Println("update key", value.Key, define, value.Value)
				prop.instance.MergeProp(define[value.Key], value.Value)
			}
		}
		//fmt.Println("sync extend", extend, prop.Define)
		return prop.Define, true
	}
	return nil, false
}

const MapPropType cooperate.PropType = "mapProp"

//msgp:tuple MapProp
type MapProp struct {
	Identity  int                `json:"identity" msg:"identity"`
	MapNoId   string             `json:"mapNoId" msg:"mapNoId"`
	Position  []byte             `json:"position" msg:"position"`
	Type      byte               `json:"type" msg:"type"`
	Key       string             `json:"key" msg:"key"`
	DoSustain *cooperate.Sustain `json:"do_sustain" msg:"do_sustain"`

	Listen   [][]byte `json:"-" msg:"-"`
	instance cooperate.PropsInstance
}

func NewMapProp(instance cooperate.PropsInstance) *MapProp {
	listen := cooperate.NewPositionsBy(instance.GetProp(Listen))
	//if instance.GetDataType() == UnitType {
	//	fmt.Println("listen a", instance.BaseData(), instance.ToBytes(Listen), listen)
	//}
	instance.MergeProp(Listen, listen)
	position := instance.ToBytes(Position)
	//fmt.Println("map prop", instance.Data(), instance.GetProp(Position), position)
	instance.MergeProp(Position, position)

	return &MapProp{
		Identity:  instance.ToInt(Identity),
		MapNoId:   instance.ToString(MapNoId),
		Position:  instance.ToBytes(Position),
		Type:      instance.ToByte(Type),
		Key:       instance.ToString(Key),
		DoSustain: cooperate.NewSustainBy(instance.GetProp(DoSustain)),

		Listen:   listen,
		instance: instance,
	}
}

func ReceiveMapProp(instance cooperate.PropsInstance) *MapProp {
	prop := instance.Receive(MapPropType)
	if prop == nil {
		return nil
	}
	return prop.(*MapProp)
}
func FromMapProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Identity, MapNoId, Position, Type, Key, DoSustain).BindChess(Identity, Type, Key, DoSustain).BindPersistence(Identity, MapNoId, Position, Type, Key, Listen)
}
func (prop *MapProp) ChessProp(data *chess_protocol.Data) {
	data.Position = prop.Position
	data.Props = append(data.Props, prop.Identity, prop.Type, prop.Key)
	if prop.DoSustain == nil {
		data.Props = append(data.Props, nil)
	} else {
		data.Props = append(data.Props, prop.DoSustain)
	}
}
func (prop *MapProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Identity:
		prop.Identity = utils.ToInt(value)
		return prop.Identity, true
	case MapNoId:
		prop.MapNoId = utils.ToString(value)
		return prop.MapNoId, true
	case Position:
		//fmt.Println("position", prop.instance.BaseData(), prop.Position, utils.ToBytes(value), time.Now().Unix())
		prop.Position = utils.ToBytes(value)
		return prop.Position, true
	case Type:
		prop.Type = utils.ToByte(value)
		return prop.Type, true
	case Key:
		prop.Key = utils.ToString(value)
		return prop.Key, true
	case Listen:
		//fmt.Println("update listen", value, utils.ToBytesSlice(value))
		prop.Listen = utils.ToBytesSlice(value)
		return prop.Listen, true
	case DoSustain:
		prop.DoSustain = cooperate.NewSustainBy(value)
	}
	return nil, false
}
func (prop *MapProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

func (prop *MapProp) GetPosition() []byte {
	return prop.Position
}
func (prop *MapProp) GetIdentity() int {
	return prop.Identity
}
func (prop *MapProp) GetType() byte {
	return prop.Type
}
func (prop *MapProp) GetRelationLink() map[byte][][]byte {
	//fmt.Println("listen", prop.Listen)
	return map[byte][][]byte{
		ListenRelation: prop.Listen,
	}
}

const MovePropType cooperate.PropType = "moveProp"

//msgp:tuple MoveProp
type MoveProp struct {
	Direction []byte                  `json:"direction" msg:"direction"`
	Plan      cooperate.PositionSlice `json:"plan" msg:"plan"`
	PlanIndex byte                    `json:"planIndex" msg:"planIndex"`
	Positions cooperate.PositionSlice `json:"positions" msg:"positions"`

	Visible TargetVisible `json:"visible" msg:"visible"`
	Ignore  bool          `json:"ignore" msg:"ignore"`

	LastRegion []byte `json:"lastRegion" msg:"lastRegion"`

	Speed       int `json:"speed" msg:"speed"`
	SpeedChange int `json:"speedChange" msg:"speedChange"`

	Status bool `json:"status" msg:"status"`

	BehaviorPattern byte `json:"behaviorPattern" msg:"behaviorPattern"`

	abilityProp *AbilityProp            `json:"-" msg:"-"`
	instance    cooperate.PropsInstance `json:"-" msg:"-"`
}

func NewMoveProp(instance cooperate.PropsInstance, ability *AbilityProp) *MoveProp {
	plan := cooperate.NewPositions(instance.ToBytes(Plan))
	//fmt.Println("move prop", instance.ToBytes(Plan), plan)
	instance.MergeProp(Plan, plan)
	positions := cooperate.NewPositions(instance.ToBytes(Positions))
	//fmt.Println("move prop", instance.ToBytes(Positions), positions)
	instance.MergeProp(Positions, positions)
	return &MoveProp{
		Direction: instance.ToBytes(Direction),
		Plan:      plan,
		PlanIndex: instance.ToByte(PlanIndex),
		Positions: positions,

		Visible:    TargetVisible(instance.ToInt(Visible)),
		Ignore:     instance.ToBool(Ignore),
		Status:     instance.ToBool(MoveStatus),
		LastRegion: instance.ToBytes(LastRegion),

		Speed:           ability.GetAttrWithKey(Speed),
		SpeedChange:     ability.GetAttrWithKey(SpeedChange),
		BehaviorPattern: instance.ToByte(BehaviorPattern),

		abilityProp: ability,
		instance:    instance,
	}
}
func ReceiveMoveProp(instance cooperate.PropsInstance) *MoveProp {
	prop := instance.Receive(MovePropType)
	if prop == nil {
		return nil
	}
	return prop.(*MoveProp)
}
func FromMoveProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Direction, Plan, PlanIndex, Positions, Visible, Ignore, LastRegion, Speed, SpeedChange, MoveStatus, BehaviorPattern).
		BindChess(Direction, Plan, PlanIndex, Positions, Visible, Speed, SpeedChange, MoveStatus).
		BindPersistence(Direction, Plan, PlanIndex, Positions, Ignore, LastRegion, MoveStatus, BehaviorPattern)

	fd.Register(AttrAbility, MovePropType)
}
func (prop *MoveProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Direction, prop.Plan, prop.PlanIndex, prop.Positions, prop.Visible, prop.Speed, prop.SpeedChange, prop.Status)
}
func (prop *MoveProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Direction:
		prop.Direction = utils.ToBytes(value)
		return prop.Direction, true
	case Plan:
		prop.Plan = utils.ToBytesSlice(value)
		return prop.Plan, true
	case PlanIndex:
		prop.PlanIndex = utils.ToByte(value)
		return prop.PlanIndex, true
	case Positions:
		prop.Positions = utils.ToBytesSlice(value)
		return prop.Positions, true
	case Visible:
		prop.Visible = TargetVisible(utils.ToInt(value))
	case Ignore:
		prop.Ignore = utils.ToBool(value)
	case LastRegion:
		prop.LastRegion = utils.ToBytes(value)
	case MoveStatus:
		prop.Status = utils.ToBool(value)
	case AttrAbility:
		fd := DataTypeFieldMap[prop.instance.GetDataType()]
		speed := prop.abilityProp.GetAttrWithKey(Speed)
		if speed != prop.Speed {
			prop.Speed = speed
			content.Props = append(content.Props, chess_protocol.UpdateProp{
				Key:   byte(fd.NoticeProp[Speed]),
				Value: speed,
			})
		}
		speedChange := prop.abilityProp.GetAttrWithKey(SpeedChange)
		if speedChange != prop.SpeedChange {
			prop.SpeedChange = speedChange
			content.Props = append(content.Props, chess_protocol.UpdateProp{
				Key:   byte(fd.NoticeProp[SpeedChange]),
				Value: speed,
			})
		}
	case BehaviorPattern:
		prop.BehaviorPattern = utils.ToByte(value)
	}
	return nil, false
}
func (prop *MoveProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}
func (prop *MoveProp) GetPositions() [][]byte {
	return nil
}
func (prop *MoveProp) IsSeat() bool {
	return true
}
func (prop *MoveProp) IsFixed() bool {
	return false
}
func (prop *MoveProp) IsNode() bool {
	return false
}
func (prop *MoveProp) GetExtend() []byte {
	extend := &pathfinding.StrategyExtend{
		Time:    0,
		Visible: int(prop.Visible),
		Next:    nil,
	}
	return extend.Get()
}

const FixPropType cooperate.PropType = "fixProp"

//msgp:tuple FixProp
type FixProp struct {
	Direction []byte   `json:"direction" msg:"direction"`
	Positions [][]byte `json:"positions" msg:"positions"`
	BuildMode byte     `json:"buildMode" msg:"buildMode"`
	Obvious   byte     `json:"obvious" msg:"obvious"`
}

func NewFixProp(instance cooperate.PropsInstance) *FixProp {
	//fmt.Println("fix", instance.GetProp(Positions), cooperate.NewPositionsBy(instance.GetProp(Positions)))
	positions := cooperate.NewPositionsBy(instance.GetProp(Positions))
	instance.MergeProp(Positions, positions)
	return &FixProp{
		Direction: instance.ToBytes(Direction),
		Positions: positions,
		BuildMode: instance.ToByte(BuildMode),
		Obvious:   instance.ToByte(Obvious),
	}
}
func ReceiveFixProp(instance cooperate.PropsInstance) *FixProp {
	prop := instance.Receive(FixPropType)
	if prop == nil {
		return nil
	}
	return prop.(*FixProp)
}
func FromFixProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Direction, Positions, BuildMode, Obvious).BindChess(Direction, Positions, BuildMode, Obvious).
		BindPersistence(Direction, Positions, BuildMode, Obvious)
}
func (prop *FixProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Direction, prop.Positions, prop.BuildMode, prop.Obvious)
}

func (prop *FixProp) GetPositions() [][]byte {
	return prop.Positions
}
func (prop *FixProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Direction:
		prop.Direction = utils.ToBytes(value)
		return prop.Direction, true
	case Positions:
		prop.Positions = cooperate.NewPositionsBy(value)

		//fmt.Println("fix update", value, prop.Positions)
		return prop.Positions, true
	case BuildMode:
		prop.BuildMode = utils.ToByte(value)
		return prop.BuildMode, true
	case Obvious:
		prop.Obvious = utils.ToByte(value)
		return prop.Obvious, true
	}
	return nil, false
}
func (prop *FixProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}
func (prop *FixProp) IsSeat() bool {
	return false
}
func (prop *FixProp) IsFixed() bool {
	return true
}
func (prop *FixProp) IsNode() bool {
	return true
}
func (prop *FixProp) GetExtend() []byte {
	return nil
}

const AbilityPropType cooperate.PropType = "abilityProp"

type BuffTimeInfo struct {
	BuffId   int
	Time     int
	Value    int
	NextTime int
}

//msgp:tuple AbilityProp
type AbilityProp struct {
	Level             int                         `json:"level" msg:"level"`
	BuffAbilityExtend []chess_protocol.ExtendItem `json:"buffAbilityExtend" msg:"buffAbilityExtend"`
	DirectIds         []int                       `json:"directIds" msg:"directIds"`
	DirectCool        []int64                     `json:"directCool" msg:"directCool"`

	View byte `json:"view" msg:"view"`

	AttrAbility game.IntAbilitySlice `json:"-" msg:"-"`
	BuffAbility game.IntAbilitySlice `json:"-" msg:"-"`

	AttrAbilityMap game.IntAbilityMap `json:"-" msg:"-"`

	BuffInfoSlice BuffInfoSlice `json:"-" msg:"-"`

	*cooperate.AbilityOwner `json:"-" msg:"-"`

	instance cooperate.PropsInstance
	logic    *TypeManager

	attrMutex   sync.RWMutex
	attrTimeMap map[int]*BuffTimeInfo

	directMutex   sync.RWMutex
	directTimeMap map[int]int64

	lastClearBuffSecond int

	relyMap map[string]cooperate.UpdateInstance

	allHealth int
}

func NewAbilityProp(logic *TypeManager, mapInstance cooperate.MapBase, instance cooperate.PropsInstance, owner *cooperate.AbilityOwner, extendMap map[structure.ExtendType]interface{}) *AbilityProp {
	//startTime := time.Now()
	effect := owner.Generate(mapInstance, instance, logic)
	//endTime := time.Now().Sub(startTime)
	//if endTime > 10*time.Millisecond {
	//	fmt.Println("ability owner", endTime, instance.BaseData())
	//}
	directIds := effect.GetIds(model.DirectAbilityDefine)
	attrAbility := game.IntAbilitySlice(effect.GetSlice(model.AttrAbilityDefine))
	buffAbility := effect.GetIds(model.BuffAbilityDefine)
	attrAbilityMap := attrAbility.ListToMap()
	timer := instance.Timer()
	attrData := logic.Center.AttrData

	var buffExtendList []chess_protocol.ExtendItem
	var buffInfoSlice BuffInfoSlice
	if extendMap[BuffAbilityExtend] != nil {
		buffSortedList := extendMap[BuffAbilityExtend].(structure.SortedDataSlice)
		buffInfoSlice = NewBuffInfoSlice(buffSortedList)
		for _, data := range buffSortedList {
			buffExtendList = append(buffExtendList, chess_protocol.ExtendItem{No: data.Score, Value: data.Value})
		}
	}
	ap := &AbilityProp{
		Level:             utils.ToInt(instance.GetProp(Level)),
		BuffAbilityExtend: buffExtendList,
		DirectIds:         directIds,
		DirectCool:        timer.List(DirectCoolPrefix, instance, directIds),

		View: utils.ToByte(attrAbilityMap.Id(attrData.KeyToId(View))),

		AttrAbility:    attrAbility,
		BuffAbility:    buffAbility,
		AttrAbilityMap: attrAbilityMap,
		BuffInfoSlice:  buffInfoSlice,
		AbilityOwner:   owner,

		instance: instance,
		logic:    logic,

		attrMutex:   sync.RWMutex{},
		attrTimeMap: map[int]*BuffTimeInfo{},

		directMutex:   sync.RWMutex{},
		directTimeMap: map[int]int64{},

		lastClearBuffSecond: logic.CurrentSecond(),

		relyMap: map[string]cooperate.UpdateInstance{},
	}

	instance.ClearTimeSorted(logic, BuffAbilityExtend, ap.BuffInfoSlice, 0, 300)
	instance.BindAbility(ap)
	return ap
}
func ReceiveAbilityProp(instance cooperate.PropsInstance) *AbilityProp {
	if instance == nil {
		return nil
	}
	prop := instance.Receive(AbilityPropType)
	if prop == nil {
		return nil
	}
	return prop.(*AbilityProp)
}
func FromAbilityProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Level, DirectIds, DirectCool, View).
		BindNoticeExtend(BuffAbilityExtend, func(execute *structure.Execute, conn structure.SafeConn, instance cooperate.PropsInstance, extend structure.ExtendType) interface{} {
			result := execute.GetSortedExtend(conn, instance, BuffAbilityExtend, 0, math.MaxInt32, true)
			return result
		}, true).
		BindNoticeExtend(DirectCoolExtend, nil, false).
		BindChess(Level, View).
		BindChessExtend(BuffAbilityExtend).
		BindServer(AttrAbility, BuffAbility).
		BindPersistence(Level)
}

func (prop *AbilityProp) GetView() byte {
	return prop.View
}

func (prop *AbilityProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Level, prop.View)
	data.Extend = append(data.Extend, prop.BuffAbilityExtend)
}
func (prop *AbilityProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	timer := prop.instance.Timer()
	switch key {
	case View:
		prop.View = utils.ToByte(value)
		//fmt.Println("view", prop.View, value)
	case Level:
		prop.Level = utils.ToInt(value)
	case AttrAbility:
		//fmt.Println("attr ability", value)
		// 设置为已经更改，如果需要获取，则会自动更新
		prop.AbilityOwner.Change()
		prop.AttrAbility = game.NewIntAbilitySliceBy(value)
		prop.AttrAbilityMap = prop.AttrAbility.ListToMap()

		fd := DataTypeFieldMap[prop.instance.GetDataType()]
		view := utils.ToByte(prop.GetAttrWithKey(View))
		if view != prop.View {
			prop.View = view
			content.Props = append(content.Props, chess_protocol.UpdateProp{
				Key:   byte(fd.NoticeProp[View]),
				Value: view,
			})
		}

		// 属性变更，需要重新计算buff叠加，下发叠加后的数值
		m := prop.AnalysisBuff(prop.BuffInfoSlice, prop.AttrAbilityMap)
		prop.attrMutex.RLock()
		diff := prop.ComputeDiffBuff(m, prop.attrTimeMap)
		prop.attrMutex.RUnlock()
		prop.attrTimeMap = m

		for key, value := range diff {
			fIndex, ok := fd.NoticeProp[key]
			if !ok {
				continue
			}
			content.Props = append(content.Props, chess_protocol.UpdateProp{Key: byte(fIndex), Value: value})
		}
		return prop.AttrAbility, true
	case BuffAbility:
		// 设置为已经更改，如果需要获取，则会自动更新
		prop.AbilityOwner.Change()
		prop.BuffAbility = game.NewIntAbilitySliceBy(value)
		return prop.BuffAbility, true
	case DirectIds:
		// 设置为已经更改，如果需要获取，则会自动更新
		prop.AbilityOwner.Change()
		prop.DirectIds = game.NewIntAbilitySliceBy(value)
		// 更新冷却时间
		if len(prop.DirectIds) > 0 {
			prop.DirectCool = make([]int64, len(prop.DirectIds))
			for index, id := range prop.DirectIds {
				prop.directMutex.RLock()
				prop.DirectCool[index] = prop.directTimeMap[id]
				prop.directMutex.RUnlock()
			}
		} else {
			prop.DirectCool = []int64{}
		}
		fd := DataTypeFieldMap[prop.instance.GetDataType()]
		content.Props = append(content.Props, chess_protocol.UpdateProp{
			Key:   byte(fd.NoticeProp[DirectCool]),
			Value: prop.DirectCool,
		})
		return prop.DirectIds, true
	default:
		prefix := strings.HasPrefix(key, DirectCoolPrefix)
		if prefix {
			fd := DataTypeFieldMap[prop.instance.GetDataType()]
			id, index, value, extend := timer.Update(fd.NoticeExtend[DirectCoolExtend], DirectCoolPrefix, prop.DirectIds, key, value)
			prop.directMutex.Lock()
			prop.directTimeMap[id] = value
			prop.directMutex.Unlock()
			if extend != nil {
				prop.DirectCool[index] = value
				content.Extend = append(content.Extend, *extend)
			}
		}
	}
	return nil, false
}
func (prop *AbilityProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	if extend == BuffAbilityExtend {
		exSlice := prop.BuffAbilityExtend
		infoSlice := prop.BuffInfoSlice
		if total.Reset != nil {
			exSlice = exSlice[0:0]
			for _, data := range total.Reset {
				exSlice = append(exSlice, data)
				infoSlice = append(infoSlice, *NewBuffInfoBy(utils.ToBytes(data.Value), data.No))
			}
		} else {
			for _, data := range total.List {
				value := utils.ToBytes(data.Value)
				if data.Key == chess_protocol.InsertOperateExtend {
					exSlice = append(exSlice, chess_protocol.ExtendItem{No: data.No, Value: data.Value})
					infoSlice = append(infoSlice, *NewBuffInfoBy(utils.ToBytes(data.Value), data.No))
					info := infoSlice[len(infoSlice)-1]
					buff := prop.logic.SkillData.BuffMap[info.BuffId]
					info.IsSave = buff.IsSave
				} else if data.Key == chess_protocol.DeleteOperateExtend {
					i := -1
					if data.No > 0 {
						for index, b := range exSlice {
							if b.No == data.No {
								i = index
								break
							}
						}
					} else if data.Value != nil {
						bb := utils.ToBytes(value)
						for index, b := range exSlice {
							if bytes.Equal(utils.ToBytes(b.Value), bb) {
								i = index
								break
							}
						}
					}
					if i >= 0 {
						exSlice = append(exSlice[0:i], exSlice[i+1:]...)
						infoSlice = append(infoSlice[0:i], infoSlice[i+1:]...)
					}
				} else if data.Key == chess_protocol.BatchDeleteOperateExtend {
					end := utils.ToInt(data.Value)
					flagIndex := -1
					for index, info := range infoSlice {
						if info.Time <= end {
							flagIndex = index
						} else {
							break
						}
					}
					if flagIndex >= 0 {
						exSlice = exSlice[flagIndex:]
						infoSlice = infoSlice[flagIndex:]
					}
					// 保存更新时间
					prop.lastClearBuffSecond = end
				}
			}
		}
		prop.BuffAbilityExtend = exSlice
		prop.BuffInfoSlice = infoSlice

		m := prop.AnalysisBuff(prop.BuffInfoSlice, prop.AttrAbilityMap)
		prop.attrMutex.RLock()
		diff := prop.ComputeDiffBuff(m, prop.attrTimeMap)
		prop.attrMutex.RUnlock()
		prop.attrTimeMap = m

		fd := DataTypeFieldMap[prop.instance.GetDataType()]
		for key, value := range diff {
			fIndex, ok := fd.NoticeProp[key]
			if !ok {
				continue
			}
			content.Props = append(content.Props, chess_protocol.UpdateProp{Key: byte(fIndex), Value: value})
		}
		return prop.BuffAbilityExtend, true
	}
	return nil, false
}

func (prop *AbilityProp) GetAttr(id int) (value int, time int) {
	attr := prop.logic.AttrData.AttrMap[id]
	if attr.IsData {
		// 战斗动态data，直接从result中获取实时数据
		return prop.instance.ToInt(attr.Key), 0
	}
	if attr.IsBattle {
		// 战斗属性，暂不考虑buff动态变更
		return prop.AttrAbilityMap.Id(id), 0
	}
	flag := false

	prop.attrMutex.RLock()
	v, ok := prop.attrTimeMap[id]
	prop.attrMutex.RUnlock()
	if ok {
		if v.Time > prop.logic.CurrentSecond() {
			value = v.Value
			time = v.Time
		} else {
			flag = true
		}
	}
	if flag {
		// 再次查询buff，看是否还需要更新状态
		m := prop.AnalysisBuff(prop.BuffInfoSlice, prop.AttrAbilityMap)
		if vv, ok := m[id]; ok {
			value = vv.Value
			time = vv.Time
		} else {
			ok = false
		}
		prop.attrMutex.RLock()
		diff := prop.ComputeDiffBuff(m, prop.attrTimeMap)
		prop.attrMutex.RUnlock()
		prop.attrTimeMap = m

		if len(diff) > 0 {
			// 将产生变更的属性提交操作，进入同步流程
			operates := []cooperate.UpdateOperateContent{}
			for key, value := range diff {
				operates = append(operates, cooperate.UpdateOperateContent{
					Operate: cooperate.ChangeData,
					Key:     key,
					Value:   value,
				})
			}
			if len(operates) > 0 {
				operateData := &cooperate.UpdateOperateData{
					Data:     *structure.NewBaseDataFrom(prop.instance),
					Operates: operates,
				}
				updateData := cooperate.OperateContent{
					MapNoId: utils.ToString(prop.instance.GetProp(MapNoId)),
					Target:  &operateData.Data,
					Operates: []cooperate.OperateData{
						cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
					},
				}
				prop.logic.PushOperate(updateData, 100)
			}
		}

	}
	value += prop.AttrAbilityMap.Id(id)
	return
}

func (prop *AbilityProp) GetDirectCool(directId int) int64 {
	prop.directMutex.RLock()
	value := prop.directTimeMap[directId]
	prop.directMutex.RUnlock()
	return value
}

func (prop *AbilityProp) GetAttrWithKey(key string) int {
	id := prop.logic.AttrData.KeyToId(key)
	return prop.GetAttrWithId(id)
}

func (prop *AbilityProp) GetAttrWithId(id int) int {
	if id == 0 {
		return 0
	}
	value, _ := prop.GetAttr(id)
	return value
}

func (prop *AbilityProp) GetAttrAddition(origin int, addition int) int {
	return origin * (100.0 + addition) / 100
}

func (prop *AbilityProp) ChangeAttr(attr game.IntAbilitySlice) map[string]interface{} {
	// 重新计算
	attrMap := attr.ListToMap()
	// 对比attrmap, 还需要计算buff叠加: 得到的是originmap
	diff := attrMap.Diff(prop.AttrAbilityMap)
	m := map[string]interface{}{}
	for id, value := range diff {
		attr := prop.logic.AttrData.AttrMap[id]
		if attr.IsData || attr.IsBattle {
			continue
		}
		if v, ok := prop.attrTimeMap[id]; ok {
			m[attr.Key] = v.Value + value
		} else {
			m[attr.Key] = value
		}
	}
	return m
}

// 属性分3种：战斗变更data，战斗属性，普通属性
// 战斗变更data：客户端处理，runtime数据，单个key，更新到redis，客户端创建初始化
// 战斗属性，直接通过buff变更，不会返回
// 普通属性，如果动态变更则内存记录变更时长以及值（记录最短的生效时长以及对应的值）
func (prop *AbilityProp) AddBuff(buffInfo *BuffInfo) map[string]interface{} {
	if buffInfo.StartTime > prop.logic.CurrentSecond() {
		return map[string]interface{}{}
	}
	buff, ok := prop.logic.SkillData.BuffMap[buffInfo.BuffId]
	if !ok {
		return map[string]interface{}{}
	}
	m := map[string]interface{}{}
	// 只返回 普通属性变更逻辑
	// addBuff只会处理新增的和变更的，
	// time-1，保证在notice接收到通知更新buffextend时能再次更新到
	for id, value := range buff.Attr {
		attr := prop.logic.AttrData.AttrMap[id]
		if attr.IsData || attr.IsBattle {
			continue
		}
		prop.attrMutex.RLock()
		v, ok := prop.attrTimeMap[id]
		prop.attrMutex.RUnlock()
		if ok {
			if v.Time > buffInfo.Time {
				// 当前buff可以立即生效
				old := prop.logic.SkillData.BuffMap[v.BuffId]
				if buff.Define > 0 && old.Define == buff.Define && old.DefineLevel > buff.DefineLevel {
					continue
				}
				// 叠加
				if old.Overlying {
					value = v.Value + value
				} else {
					value = value
				}
			}
		} else {
			ok = true
		}
		if ok {
			prop.attrMutex.Lock()
			// time-1确保通知更新后也能得到需要更新的属性
			prop.attrTimeMap[id] = &BuffTimeInfo{BuffId: buff.Id, Time: buffInfo.Time - 1, Value: value}
			prop.attrMutex.Unlock()
			m[attr.Key] = value + prop.AttrAbilityMap.Id(id)
		}
	}
	return m
}

func (prop *AbilityProp) RemoveBuff(buffInfo *BuffInfo, number int, pass interface{}) (map[string]interface{}, interface{}) {
	_, ok := prop.logic.SkillData.BuffMap[buffInfo.BuffId]
	if !ok {
		return map[string]interface{}{}, pass
	}
	i := -1
	for index, buff := range prop.BuffInfoSlice {
		if buff.BuffId == buffInfo.Id && buff.DataType == buffInfo.DataType && buff.Id == buffInfo.Id {
			buffInfo.Time = buff.Time
			buffInfo.StartTime = buff.StartTime
			i = index
			break
		}
	}
	currentSecond := prop.logic.CurrentSecond()
	if buffInfo.Time == 0 || buffInfo.Time < currentSecond || buffInfo.StartTime > currentSecond {
		// 没有找到，直接返回，或者没有生效
		return map[string]interface{}{}, pass
	}
	var pp BuffInfoSlice
	if pass == nil {
		pp = prop.BuffInfoSlice
	} else {
		pp, ok = pass.(BuffInfoSlice)
		if !ok {
			pp = prop.BuffInfoSlice
		}
	}
	if i == 0 {
		pp = pp[1:]
	} else if i == len(pp)-1 {
		pp = pp[0:i]
	} else {
		pp = append(pp[:i], pp[i+1:]...)
	}
	if number > 0 {
		// 不是最后个，记录在pass中
		return map[string]interface{}{}, pp
	}
	m := prop.AnalysisBuff(pp, prop.AttrAbilityMap)

	prop.attrMutex.RLock()
	diff := prop.ComputeDiffBuff(m, prop.attrTimeMap)
	prop.attrMutex.RUnlock()
	return diff, pp
}

func (prop *AbilityProp) AnalysisBuff(bis BuffInfoSlice, attrMap game.IntAbilityMap) map[int]*BuffTimeInfo {
	b := prop.logic.GroupDistinctBuff(bis.Distinct(prop.BuffAbility))
	m := map[int]*BuffTimeInfo{}
	currentSecond := prop.logic.CurrentSecond()
	for _, buffInfo := range bis {
		if buffInfo.StartTime > currentSecond {
			continue
		}
		if buffInfo.Time < currentSecond {
			continue
		}

		buff, ok := b[buffInfo.BuffId]
		if !ok {
			// 过滤掉了
			continue
		}
		for id, value := range buff.Attr {
			attr := prop.logic.AttrData.AttrMap[id]
			if attr.IsData || attr.IsBattle {
				continue
			}
			v, ok := m[attr.Id]
			if ok {
				if v.Time > buffInfo.Time {
					// group和level关系在Distinct时已经过滤完毕
					if buff.Overlying {
						v.Value += value
					} else {
						v.Value = value
					}
					v.Time = buffInfo.Time
				}
			} else {
				m[attr.Id] = &BuffTimeInfo{BuffId: buff.Id, Time: buffInfo.Time, Value: value}
			}
		}
	}
	return m
}

func (prop *AbilityProp) ClearBuff() []cooperate.UpdateOperateContent {
	//builder := logic.OperateBuilder()
	//builder.BindMapNoId(logic.GetMapNoId()).Target(*prop.instance.Data())
	//builder.Update(*prop.instance.Data(), nil)
	//i := 0
	//for index, buffInfo := range prop.BuffInfoSlice {
	//	if buffInfo.IsSave {
	//		continue
	//	}
	//	extendItem := prop.BuffAbilityExtend[index]
	//	builder.RemoveTimeSorted(string(BuffAbilityExtend), extendItem.Value)
	//	i += 1
	//}
	//if i > 0 {
	//	fmt.Println("clear buff", i)
	//	builder.Operate(0, nil)
	//}
	operates := []cooperate.UpdateOperateContent{}
	for index, buffInfo := range prop.BuffInfoSlice {
		if buffInfo.IsSave {
			continue
		}
		extendItem := prop.BuffAbilityExtend[index]
		operates = append(operates, cooperate.UpdateOperateContent{
			Key:     string(BuffAbilityExtend),
			Operate: cooperate.RemoveTimeSorted,
			Value:   extendItem.Value,
		})
		fmt.Println("clear buff", buffInfo.BuffId, buffInfo.Id)
	}
	return operates
}

func (prop *AbilityProp) ComputeDiffBuff(m map[int]*BuffTimeInfo, origin map[int]*BuffTimeInfo) map[string]interface{} {
	mm := map[string]interface{}{}
	for id, info := range m {
		flag := false
		value := 0
		vv, ok := origin[id]
		if ok {
			if info.Time != vv.Time || info.Value != vv.Value {
				// 变更
				flag = true
				value = info.Value
			}
		} else {
			// 新增
			flag = true
		}
		if flag {
			attr := prop.logic.AttrData.AttrMap[id]
			mm[attr.Key] = value + prop.AttrAbilityMap.Id(id)
		}
	}

	for id, _ := range origin {
		flag := false
		value := 0
		if _, ok := m[id]; !ok {
			// 移除
			flag = true
		}
		if flag {
			attr := prop.logic.AttrData.AttrMap[id]
			mm[attr.Key] = value + prop.AttrAbilityMap.Id(id)
		}
	}
	return mm
}

const BattlePropType cooperate.PropType = "battleProp"

//msgp:tuple InjuryItem
type InjuryItem struct {
	structure.BaseData `json:"data" msg:"data"`
	Score              int32 `json:"score" msg:"score"`
}

func (item *InjuryItem) ToString() string {
	return utils.ToString(item.BaseData.GetItem())
}

func NewInjuryItemBy(obj interface{}) *InjuryItem {
	if obj == nil {
		return nil
	}
	switch t := obj.(type) {
	case *InjuryItem:
		return t
	}
	os := utils.ToInterfaceSlice(obj)
	if os == nil {
		return nil
	}
	v := &InjuryItem{BaseData: structure.BaseData{
		DataType: structure.PublicDataType(utils.ToInt(os[0])),
		Id:       utils.Copy(os[1]),
	}}
	v.Score = utils.ToInt32(os[2])
	return v
}

//msgp:tuple InjurySlice
type InjurySlice struct {
	Total int32        `json:"total" msg:"total"`
	Items []InjuryItem `json:"items" msg:"items"`
}

func (injury InjurySlice) Clear() {
	injury.Total = 0
	injury.Items = injury.Items[0:0]
}

//msgp:tuple BattleProp
type BattleProp struct {
	Health    int  `json:"health" msg:"health"`
	AllHealth int  `json:"allHealth" msg:"allHealth"`
	Combat    bool `json:"combat" msg:"combat"`

	AttackTarget *structure.BaseData `json:"attackTarget" msg:"attackTarget"`

	BehaviorSlice `json:"-" msg:"-"`

	// 只保留在当前服务节点，只通过operate更新，当destroy时也是通过operate判断执行
	//
	*InjurySlice `json:"-" msg:"-"`

	instance    cooperate.PropsInstance
	abilityProp *AbilityProp
}

func NewBattleProp(ability *AbilityProp, instance cooperate.PropsInstance) *BattleProp {
	attackObject := structure.NewBaseDataBy(instance.GetProp(AttackTarget))
	// 确保instance中的格式一致
	instance.MergeProp(AttackTarget, attackObject)
	return &BattleProp{
		Health:        instance.ToInt(Health),
		AllHealth:     ability.GetAttrWithKey(AllHealth),
		Combat:        false,
		AttackTarget:  attackObject,
		BehaviorSlice: NewBehaviorSliceWithBytes(instance.ToBytes(Behaviors)),

		instance:    instance,
		abilityProp: ability,
		InjurySlice: &InjurySlice{Total: 0, Items: []InjuryItem{}},
	}
}
func ReceiveBattleProp(instance cooperate.PropsInstance) *BattleProp {
	prop := instance.Receive(BattlePropType)
	if prop == nil {
		return nil
	}
	return prop.(*BattleProp)
}
func FromBattleProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(Health, AllHealth, Combat, AttackTarget).BindChess(Health, AllHealth, Combat, AttackTarget).BindServer(Behaviors).BindPersistence(Health, Behaviors).BindLocal(InjuryData)

	fd.Register(AttrAbility, BattlePropType)
}
func (prop *BattleProp) ChessProp(data *chess_protocol.Data) {
	data.Props = append(data.Props, prop.Health, prop.AllHealth, prop.Combat)
	if prop.AttackTarget == nil {
		data.Props = append(data.Props, nil)
	} else {
		data.Props = append(data.Props, prop.AttackTarget)
	}

}
func (prop *BattleProp) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case Health:
		prop.Health = utils.ToInt(value)
		return prop.Health, true
	case Combat:
		prop.Combat = utils.ToBool(value)
		if !prop.Combat {
			prop.InjurySlice.Clear()
		}
		return prop.Combat, true
	case InjuryData:
		if prop.InjurySlice == nil {
			prop.InjurySlice = &InjurySlice{Total: 0, Items: []InjuryItem{}}
		}
		//fmt.Println("injury", value)
		if value != nil && prop.Health > 0 {
			v := NewInjuryItemBy(value)
			if v != nil {
				prop.InjurySlice.Items = append(prop.InjurySlice.Items, *v)
			}
			prop.InjurySlice.Total += prop.InjurySlice.Items[len(prop.InjurySlice.Items)-1].Score
		} else {
			prop.InjurySlice.Clear()
		}
	case AttackTarget:
		prop.AttackTarget = structure.NewBaseDataBy(value)
		//fmt.Println("attack target", value, prop.AttackTarget)
		if prop.AttackTarget == nil {
			return nil, true
		} else {
			return prop.AttackTarget, true
		}
	case Behaviors:
		prop.BehaviorSlice = NewBehaviorSliceWithBytes(utils.ToBytes(value))
		return prop.BehaviorSlice, true
	case AttrAbility:
		fd := DataTypeFieldMap[prop.instance.GetDataType()]
		allHealth := prop.abilityProp.GetAttrWithKey(AllHealth)
		if allHealth != prop.AllHealth {
			prop.AllHealth = allHealth
			content.Props = append(content.Props, chess_protocol.UpdateProp{
				Key:   byte(fd.NoticeProp[AllHealth]),
				Value: allHealth,
			})
		}
	}
	return nil, false
}
func (prop *BattleProp) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

//msgp:tuple Account
type Account struct {
	*OpenProp    `json:"open_prop" msg:"open_prop"`
	*MapProp     `json:"map_prop" msg:"map_prop"`
	*AbilityProp `json:"ability_prop" msg:"ability_prop"`

	Units  []string            `json:"units" msg:"units"`
	Builds []cooperate.MapNode `json:"builds" msg:"builds"`
	Nodes  []cooperate.MapNode `json:"nodes" msg:"nodes"`
	Items  []int               `json:"items" msg:"items"`

	AllianceId int `json:"alliance_id" msg:"alliance_id"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (account *Account) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case OpenPropType:
		return account.OpenProp
	case MapPropType:
		return account.MapProp
	case AbilityPropType:
		return account.AbilityProp
	case cooperate.InstancePropType:
		return account
	}
	return nil
}

func (account *Account) Exist() bool {
	return account != nil
}
func (account *Account) ListId(t *cooperate.BeDependDefine) []string {
	switch t.BeDepend {
	case UnitDataType:
		return account.Units
	}
	return nil
}

func (account *Account) SetListId(t *cooperate.BeDependDefine, list []string) {
	switch t.BeDepend {
	case UnitDataType:
		account.Units = list
	}
}

func (account *Account) ListNode(t *cooperate.BeDependDefine) []cooperate.MapNode {
	switch t.BeDepend {
	case BuildDataType:
		return account.Builds
	}
	return nil
}

func (account *Account) SetListNode(t *cooperate.BeDependDefine, list []cooperate.MapNode) {
	switch t.BeDepend {
	case BuildDataType:
		account.Builds = list
	}
}
func FromAccountProp(fd *cooperate.FieldsDefine) {
	fd.BindNotice(AllianceDataType).BindPersistence(AllianceDataType)
}
func (account *Account) ChessProp(data *chess_protocol.Data) {

}
func (account *Account) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case AllianceDataType:
		account.AllianceId = utils.ToInt(value)
	}
	return nil, false
}
func (account *Account) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

//msgp:tuple Fortress
type Fortress struct {
	*MapProp `json:"map_prop" msg:"map_prop"`

	Units    []string            `json:"units" msg:"units"`
	AiUnits  []string            `json:"ai_units" msg:"ai_units"`
	Builds   []cooperate.MapNode `json:"builds" msg:"builds"`
	AiBuilds []cooperate.MapNode `json:"ai_builds" msg:"ai_builds"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (fortress *Fortress) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case MapPropType:
		return fortress.MapProp
	}
	return nil
}

func (fortress *Fortress) Exist() bool {
	return fortress != nil
}
func (fortress *Fortress) ListId(t *cooperate.BeDependDefine) []string {
	switch t.BeDepend {
	case UnitDataType:
		return fortress.Units
	case AiUnit:
		return fortress.AiUnits
	}
	return nil
}

func (fortress *Fortress) SetListId(t *cooperate.BeDependDefine, list []string) {
	switch t.BeDepend {
	case UnitDataType:
		fortress.Units = list
	case AiUnit:
		fortress.AiUnits = list
	}
}

func (fortress *Fortress) ListNode(t *cooperate.BeDependDefine) []cooperate.MapNode {
	switch t.BeDepend {
	case BuildDataType:
		return fortress.Builds
	case AiBuild:
		return fortress.AiBuilds
	}
	return nil
}

func (fortress *Fortress) SetListNode(t *cooperate.BeDependDefine, list []cooperate.MapNode) {
	switch t.BeDepend {
	case BuildDataType:
		fortress.Builds = list
	case AiBuild:
		fortress.AiBuilds = list
	}
}

//msgp:tuple Region
type Region struct {
	*MapProp `json:"map_prop" msg:"map_prop"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (region *Region) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case MapPropType:
		return region.MapProp
	}
	return nil
}

func (region *Region) Exist() bool {
	return region != nil
}

//msgp:tuple Unit
type Unit struct {
	*IdProp      `json:"id_prop" msg:"id_prop"`
	*MapProp     `json:"map_prop" msg:"map_prop"`
	*MoveProp    `json:"move_prop" msg:"move_prop"`
	*AbilityProp `json:"ability_prop" msg:"ability_prop"`
	*BattleProp  `json:"battle_prop" msg:"battle_prop"`
	*SyncProp    `json:"sync_prop" msg:"sync_prop"`

	// 非地图上状态
	Status *cooperate.Sustain `json:"-" msg:"-"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (unit *Unit) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case IdPropType:
		return unit.IdProp
	case MapPropType:
		return unit.MapProp
	case MovePropType:
		return unit.MoveProp
	case AbilityPropType:
		return unit.AbilityProp
	case BattlePropType:
		return unit.BattleProp
	case SyncPropType:
		return unit.SyncProp
	case cooperate.InstancePropType:
		return unit
	}
	return nil
}

func (unit *Unit) Exist() bool {
	return unit != nil
}

func FromUnitProp(fd *cooperate.FieldsDefine) {
	fd.BindPersistence(UnitStatus)
}
func (unit *Unit) ChessProp(data *chess_protocol.Data) {

}
func (unit *Unit) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	switch key {
	case UnitStatus:
		unit.Status = cooperate.NewSustainBy(value)
	}
	return nil, false
}
func (unit *Unit) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

//msgp:tuple Build
type Build struct {
	*NodeProp    `json:"node_prop" msg:"node_prop"`
	*MapProp     `json:"map_prop" msg:"map_prop"`
	*FixProp     `json:"fix_prop" msg:"fix_prop"`
	*AbilityProp `json:"ability_prop" msg:"ability_prop"`
	*BattleProp  `json:"battle_prop" msg:"battle_prop"`
	*SyncProp    `json:"sync_prop" msg:"sync_prop"`

	Units   []string `json:"units" msg:"units"`
	AiUnits []string `json:"ai_units" msg:"ai_units"`

	*cooperate.PropInstance `json:"-" msg:"-"`
	*model.Build            `json:"-" msg:"-"`
}

func (build *Build) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case NodePropType:
		return build.NodeProp
	case MapPropType:
		return build.MapProp
	case FixPropType:
		return build.FixProp
	case AbilityPropType:
		return build.AbilityProp
	case BattlePropType:
		return build.BattleProp
	case SyncPropType:
		return build.SyncProp
	case cooperate.InstancePropType:
		return build
	}
	return nil
}

func (build *Build) Exist() bool {
	return build != nil
}

func (build *Build) ListId(t *cooperate.BeDependDefine) []string {
	switch t.BeDepend {
	case UnitDataType:
		return build.Units
	case AiUnit:
		return build.AiUnits
	}
	return nil
}

func (build *Build) SetListId(t *cooperate.BeDependDefine, list []string) {
	switch t.BeDepend {
	case UnitDataType:
		build.Units = list
	case AiUnit:
		build.AiUnits = list
	}
}
func FromBuildProp(fd *cooperate.FieldsDefine) {
}
func (build *Build) ChessProp(data *chess_protocol.Data) {
}
func (build *Build) UpdateField(key string, value interface{}, content *chess_protocol.UpdatePublicData) (interface{}, bool) {

	return nil, false
}
func (build *Build) UpdateExtend(extend structure.ExtendType, total *chess_protocol.UpdateExtendTotal, content *chess_protocol.UpdatePublicData) (interface{}, bool) {
	return nil, false
}

//msgp:tuple Node
type Node struct {
	*NodeProp `json:"node_prop" msg:"node_prop"`
	*MapProp  `json:"map_prop" msg:"map_prop"`
	*SyncProp `json:"sync_prop" msg:"sync_prop"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (node *Node) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case NodePropType:
		return node.NodeProp
	case MapPropType:
		return node.MapProp
	case SyncPropType:
		return node.SyncProp
	}
	return nil
}
func (node *Node) Exist() bool {
	return node != nil
}
func (node *Node) IsFixed() bool {
	return false
}
func (node *Node) IsSeat() bool {
	return false
}
func (node *Node) IsNode() bool {
	return true
}
func (node *Node) GetView() byte {
	return 0
}
func (node *Node) GetExtend() []byte {
	return nil
}
func (node *Node) GetPositions() [][]byte {
	return [][]byte{node.Position}
}

//msgp:tuple Item
type Item struct {
	*IdProp      `json:"id_prop" msg:"id_prop"`
	*MapProp     `json:"map_prop" msg:"map_prop"`
	*FixProp     `json:"fix_prop" msg:"fix_prop"`
	*AbilityProp `json:"ability_prop" msg:"ability_prop"`
	*BattleProp  `json:"battle_prop" msg:"battle_prop"`
	*SyncProp    `json:"sync_prop" msg:"sync_prop"`

	*cooperate.PropInstance `json:"-" msg:"-"`
}

func (item *Item) Receive(k cooperate.PropType) cooperate.UpdateInstance {
	switch k {
	case IdPropType:
		return item.IdProp
	case MapPropType:
		return item.MapProp
	case FixPropType:
		return item.FixProp
	case AbilityPropType:
		return item.AbilityProp
	case BattlePropType:
		return item.BattleProp
	case SyncPropType:
		return item.SyncProp
	}
	return nil
}

func (item *Item) Exist() bool {
	return item != nil
}
func (item *Item) IsFixed() bool {
	return false
}
func (item *Item) IsSeat() bool {
	return false
}

//msgp:tuple AttackObject
type AttackObject struct {
	DataType          structure.PublicDataType    `json:"data_type" msg:"data_type"`
	Id                interface{}                 `json:"id" msg:"id"`
	Identity          int                         `json:"identity" msg:"identity"`
	Key               string                      `json:"key" msg:"key"`
	Position          []byte                      `json:"position" msg:"position"`
	Visible           TargetVisible               `json:"visible" msg:"visible"`
	Direction         []byte                      `json:"direction" msg:"direction"`
	Readying          bool                        `json:"readying" msg:"readying"`
	Crossed           bool                        `json:"cross" msg:"cross"`
	BeCross           bool                        `json:"beCross" msg:"beCross"`
	AttrAbility       game.IntAbilitySlice        `json:"attrAbility" msg:"attrAbility"`
	BuffAbility       game.IntAbilitySlice        `json:"buffAbility" msg:"buffAbility"`
	BuffAbilityExtend []chess_protocol.ExtendItem `json:"buffAbility" msg:"buffAbility"`

	attr game.IntAbilityMap `json:"-" msg:"-"`
}

// 追击：Follow-true
//		移动：LastPosition设置为目的地，Target-无，CanAttack-false
//      攻击：LastPosition为空，Target-有，CanAttack-true
// 防御：Follow-false, CanAttack-false, Target-为空, LastPosition为空
// 驻守：Follow-false, CanAttack-true, Target-为空, LastPosition为空，ListenNode为列表
// 偷袭：Follow-false, CanAttack-true, Target-为空, LastPosition起始点

//msgp:tuple AttackLogic
type AttackLogic struct {
	// 追击
	Follow bool `json:"follow" msg:"follow"`
	// 主动攻击
	CanAttack bool        `json:"be_attack" msg:"be_attack"`
	Range     TargetRange `json:"range" msg:"range"`
	// 畅通无阻的点
	Pass [][]byte `json:"pass" msg:"pass"`

	// 特定行为，如果为空，则
	Behaviors BehaviorSlice `json:"behaviors" msg:"behaviors"`

	// 内部赋值，不进行序列化
	AttackDistance int    `json:"-" msg:"-"`
	FollowDistance int    `json:"-" msg:"-"`
	Position       []byte `json:"-" msg:"-"`
}

func (attack *AttackLogic) Init(attackDistance int, followDistance int, position []byte) {
	attack.AttackDistance = attackDistance
	attack.FollowDistance = followDistance
	attack.Position = position
	if attack.Follow {
		if !attack.CanAttack {
			attack.FollowDistance = -1
		}
	} else {
		attack.FollowDistance = 0
	}
}

func (attack *AttackLogic) GetRange() TargetRange {
	return attack.Range
}
func (attack *AttackLogic) GetDistance() int {
	return int(attack.AttackDistance)
}
func (attack *AttackLogic) GetPosition() []byte {
	return attack.Position
}
func (attack *AttackLogic) CanVisible() bool {
	return true
}

// 监听逻辑
//msgp:tuple ListenLogic
type ListenLogic struct {
	Nodes    cooperate.PositionSlice `json:"nodes" msg:"nodes"`
	Identity TargetIdentity          `json:"identity" msg:"identity"`
	Events   []byte                  `json:"events" msg:"events"`
	Switch   bool                    `json:"switch" msg:"switch"`

	EventsData []*structure.EventData `json:"-" msg:"-"`
}

// 探查逻辑
//msgp:tuple SearchLogic
type SearchLogic struct {
	Nodes cooperate.PositionSlice `json:"nodes" msg:"nodes"`
}

//msgp:tuple BuffInfo
type BuffInfo struct {
	BuffId    int                      `json:"buff_id" msg:"buff_id"`
	DataType  structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id        interface{}              `json:"id" msg:"id"`
	StartTime int                      `json:"start_time" msg:"start_time"`
	Time      int                      `json:"-" msg:"-"`
	IsSave    bool                     `json:"-" msg:"-"`
}

func NewBuffInfo(buffId int, dataType structure.PublicDataType, id interface{}, startTime int) *BuffInfo {
	return &BuffInfo{
		BuffId:    buffId,
		DataType:  dataType,
		Id:        id,
		StartTime: startTime,
		Time:      0,
	}
}

func (buffInfo *BuffInfo) Bytes() []byte {
	buffB, _ := buffInfo.MarshalMsg(nil)
	return buffB
}

func NewBuffInfoBy(value []byte, second int) *BuffInfo {
	buff := &BuffInfo{}
	if _, err := buff.UnmarshalMsg(value); err != nil {
		fmt.Println("buff info by", err, value)
	}
	buff.Time = second
	return buff
}

type BuffInfoSlice []BuffInfo

func NewBuffInfoSlice(list []*structure.SortedData) BuffInfoSlice {
	l := make(BuffInfoSlice, len(list))
	for index, v := range list {
		buff := BuffInfo{}
		_, _ = buff.UnmarshalMsg(utils.ToBytes(v.Value))
		buff.Time = v.Score
		buff.IsSave = true
		l[index] = buff
	}
	return l
}

func (slice BuffInfoSlice) Distinct(buffIds []int) []int {
	for _, buff := range slice {
		buffIds = append(buffIds, buff.BuffId)
	}
	return utils.RemoveDuplicateInt(buffIds)
}

func (slice BuffInfoSlice) LastestTime() int {
	min := 0
	for _, buff := range slice {
		if buff.Time < min || min == 0 {
			min = buff.Time
		}
	}
	return min
}

//msgp:tuple Behavior
type Behavior struct {
	Id       int  `json:"id" msg:"id"`               // id
	NeedCool bool `json:"need_cool" msg:"need_cool"` // 释放最后时间:如果为0，则没有时间限制，通常用来技能连带触发效果

	CoolTime  int  `json:"-" msg:"-"` // 释放间隔
	ReadyTime int  `json:"-" msg:"-"` // 准备释放
	CastTime  int  `json:"-" msg:"-"` // 释放时间
	Distance  byte `json:"-" msg:"-"` // 释放距离

	Direct *model.Direct `json:"-" msg:"-"`
}

func (behavior *Behavior) Bind(direct *model.Direct) {
	behavior.CoolTime = direct.CoolTime
	behavior.ReadyTime = direct.ReadyTime
	behavior.CastTime = direct.CastTime
	behavior.Distance = direct.MaxDistance

	behavior.Direct = direct
}

func (behavior *Behavior) IsTarget(target *cooperate.TouchTarget) bool {
	return behavior.Direct.ValidTarget(target.GetDataType(), target.TypeId)
}
func (behavior *Behavior) GetNumber() int {
	if behavior.Direct.TargetMode == model.RangeTargetMode {
		return int(behavior.Direct.Multi)
	} else {
		return 1
	}
}
func (behavior *Behavior) GetIdentity() int {
	return behavior.Direct.TargetIdentity
}
func (behavior *Behavior) GetSkillId() int {
	return utils.ToInt(behavior.Direct.Default[0])
}

//msgp BehaviorSlice
type BehaviorSlice []Behavior

func NewBehaviorSliceWithBytes(data []byte) BehaviorSlice {
	s := BehaviorSlice{}
	if data != nil && len(data) > 0 {
		_, err := s.UnmarshalMsg(data)
		if err != nil {
			fmt.Println("behavioor slice", err)
		}
	}
	return s
}

func (behaviors BehaviorSlice) BindBase(attackDistance byte, attackSpeed int) {
	// 只有在behavior[0]的coolProp大于0时生效
	if len(behaviors) == 0 {
		return
	}
	if behaviors[0].NeedCool && attackSpeed > 0 {
		behaviors[0].Distance = attackDistance
		//fmt.Println("attackSpeed", attackSpeed)
		behaviors[0].CoolTime = attackSpeed
		behaviors[0].CastTime = attackSpeed - behaviors[0].ReadyTime
	}
}

//msgp:tuple TeleportLogic
type TeleportLogic struct {
	Position []byte `json:"position" msg:"position"`
	Target   []byte `json:"target" msg:"target"` // 瞬移目标点
}

//msgp:tuple SpeedTeleportLogic
type SpeedTeleportLogic struct {
	Target []byte              `json:"target" msg:"target"`
	Arrive structure.EventData `json:"arrive" msg:"arrive"`
}

//msgp:tuple SnipeLogic
type SnipeLogic struct {
	Target   *structure.BaseData `json:"target" msg:"target"`
	Position []byte              `json:"position" msg:"position"`
}

//msgp:tuple TauntLogic
type TauntLogic struct {
	Distance int            `json:"distance" msg:"distance"`
	Range    TargetRange    `json:"range" msg:"range"`
	Position []byte         `json:"position" msg:"position"`
	Identity TargetIdentity `json:"identity" msg:"identity"`
	LogicKey string         `json:"logicKey" msg:"logicKey"`
}

func (taunt *TauntLogic) GetRange() TargetRange {
	return taunt.Range
}
func (taunt *TauntLogic) GetDistance() int {
	return taunt.Distance
}
func (taunt *TauntLogic) GetPosition() []byte {
	return taunt.Position
}
func (taunt *TauntLogic) CanVisible() bool {
	return false
}

//msgp:tuple RepairLogic
type RepairLogic struct {
	Target    structure.BaseData `json:"target" msg:"target"`
	StartTime int64              `json:"start_time" msg:"start_time"`
	DirectId  int                `json:"direct_id" msg:"direct_id"`
}

//msgp:tuple ReturnLogic
type ReturnLogic struct {
	Position []byte `json:"position" msg:"position"`
}

type MapManualLogic struct {
}

//msgp:tuple HoldLogic
type HoldLogic struct {
	Status   byte `json:"status" msg:"status"`
	Identity int  `json:"identity" msg:"identity"`

	Data structure.BaseData `json:"data" msg:"data"`
}

// 批量更新依赖属性
//msgp:tuple BatchUpdateCustomLogic
type BatchUpdateCustomLogic struct {
	DataType      structure.PublicDataType `json:"dataType" msg:"dataType"`
	Ids           []interface{}            `json:"ids" msg:"ids"`
	TargetDepends []string                 `json:"targetDepends" msg:"targetDepends"`
	TargetKeys    [][]string               `json:"targetKeys" msg:"targetKeys"`
	Scene         string                   `json:"scene" msg:"scene"`
}

// 批量更新对象
//msgp:tuple BatchOperateCustomLogic
type BatchOperateCustomLogic struct {
	DataType   structure.PublicDataType         `json:"dataType" msg:"dataType"`
	Ids        []interface{}                    `json:"ids" msg:"ids"`
	TargetType structure.PublicDataType         `json:"type" msg:"type"`
	TargetKey  string                           `json:"key" msg:"key"`
	Operates   []cooperate.UpdateOperateContent `json:"operates" msg:"operates"`
}

//msgp:tuple CreateTask
type CreateTask struct {
	DataType structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id       interface{}              `json:"id" msg:"id"`
	Identity int                      `json:"identity" msg:"identity"`
	Key      string                   `json:"key" msg:"key"`
	Position []byte                   `json:"position" msg:"position"`
	Ability  *Ability                 `json:"ability" msg:"ability"`
	Params   []interface{}            `json:"params" msg:"params"`

	Name    string                     `json:"name" msg:"name"`
	Depends []*cooperate.DependentItem `json:"depends" msg:"depends"`
}

//msgp:tuple UpdateTask
type UpdateTask struct {
	DataType structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id       interface{}              `json:"id" msg:"id"`
	Identity int                      `json:"identity" msg:"identity"`
	Key      string                   `json:"key" msg:"key"`
	Position []byte                   `json:"position" msg:"position"`
	Ability  *Ability                 `json:"ability" msg:"ability"`
	Params   []interface{}            `json:"params" msg:"params"`

	Scene string `json:"scene" msg:"scene"`
}

//msgp:tuple DestroyTask
type DestroyTask struct {
	DataType structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id       interface{}              `json:"id" msg:"id"`
	Identity int                      `json:"identity" msg:"identity"`
	Key      string                   `json:"key" msg:"key"`
	Position []byte                   `json:"position" msg:"position"`
	Ability  *Ability                 `json:"ability" msg:"ability"`
	Params   []interface{}            `json:"params" msg:"params"`
}

//msgp:tuple DirectTask
type DirectTask struct {
	DataType       structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id             interface{}              `json:"id" msg:"id"`
	Identity       int                      `json:"identity" msg:"identity"`
	Key            string                   `json:"key" msg:"key"`
	TargetDataType structure.PublicDataType `json:"target_data_type" msg:"target_data_type"`
	TargetId       interface{}              `json:"target_id" msg:"target_id"`
	Ability        *Ability                 `json:"ability" msg:"ability"`
	Params         []interface{}            `json:"params" msg:"params"`

	DirectId int `json:"direct_id" msg:"direct_id"`
}

//msgp:tuple Ability
type Ability struct {
	Level         int                  `json:"level" msg:"level"`
	AttrAbility   game.IntAbilitySlice `json:"attrAbility" msg:"attrAbility"`
	BuffAbility   game.IntAbilitySlice `json:"buffAbility" msg:"buffAbility"`
	DirectAbility game.IntAbilitySlice `json:"directAbility" msg:"directAbility"`
}

//msgp:tuple BaseInfo
type BaseInfo struct {
	MapNoId string
	From    *structure.BaseData
	Target  *structure.BaseData
	Time    int64
}

func (info *BaseInfo) GetFrom() *structure.BaseData {
	return info.From
}
func (info *BaseInfo) GetTarget() *structure.BaseData {
	return info.Target
}
func (info *BaseInfo) GetTime() int64 {
	return info.Time
}
func (info *BaseInfo) GetMapNoId() string {
	return info.MapNoId
}

//msgp:tuple BaseFind
type BaseFind struct {
	Range    TargetRange
	Distance int
	Position []byte
	Visible  bool
}

func (find *BaseFind) GetRange() TargetRange {
	return find.Range
}
func (find *BaseFind) GetDistance() int {
	return find.Distance
}
func (find *BaseFind) GetPosition() []byte {
	return find.Position
}
func (find *BaseFind) CanVisible() bool {
	return find.Visible
}

//msgp:tuple ReadyMessage
type ReadyMessage struct {
	Center    []byte                `json:"center" msg:"center"`
	SkillId   int                   `json:"skill_id" msg:"skill_id"`
	Targets   []*structure.BaseData `json:"targets" msg:"targets"`
	Positions [][]byte              `json:"positions" msg:"positions"`
}
